#pragma once

#include "util.hpp"
#include "epoller.hpp"
#include "Task.hpp"

#define IN_BUFFER_SIZE 128
#define OUT_BUFFER_SIZE 128

namespace ns_appinterface
{
  using namespace ns_epoll;
  
  int recver(EventItem* item);
  int sender(EventItem* item);
  int errorer(EventItem* item);

  int accepter(EventItem* item)
  {
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    Epoller* epoller = item->_R;
    int listen_sock = item->_sock;
    while (1){
      int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
      if (sock < 0){
        if (errno == EAGAIN || errno == EWOULDBLOCK){
          // 没有读出错，只是底层无连接了
          return 0;
        }
        else if (errno == EINTR){
          // 无错误，被信打断，继续读  
          // accept在获取链接未就绪是接收到信号会立即返回，先处理信号
          continue;
        }
        else{
          // error
          std::cout << "accept error" << std::endl;
          return -1;
        }
      }
      else{
        // success
        // 将获取到的链接添加到epoller中

        uint16_t peerPort = ntohs(peer.sin_port);
        std::string peerIp = inet_ntoa(peer.sin_addr);
        std::cout << "get a new link, IP: " << peerIp << " Port: " << peerPort << std::endl;

        // 添加peer信息到_sock_peer中
        Peer peerMsg(peerIp, peerPort);
        epoller->_sock_peer.insert({sock, peerMsg});
        EventItem tmp; 
        
        ns_util::SetNoBlock(sock);
        tmp._sock = sock;
        tmp._R = epoller;
        tmp.ManagerCallBack(recver, sender, errorer);
        
        epoller->AddEvents(sock, tmp, EPOLLIN|EPOLLET);
      }
    }
    return 0;
  }
  int recv_helper(int sock, std::string& out)// 输出
  {
    int flag = 1;
    while (1){
      char buf[IN_BUFFER_SIZE];
      ssize_t size = recv(sock, buf, sizeof(buf)-1, 0);
      if (size < 0){
        if (errno == EWOULDBLOCK || errno == EAGAIN){
          // 无错
          // 底层数据读取完毕
          return 0;
        }
        else if (errno == EINTR){
          // 被信号中断
          continue;
        }
        else{
          // 出错
          std::cerr << "recv error, fd: " << sock << std::endl;
          return -1;
        }
      }
      else{
        // 第一次读返回值为0，说明对端关闭了
        if (flag && size == 0){
          return 1;
        }
        flag = 0;
        // 正常读取数据
        buf[size] = 0;
        out += buf;
        //if (size < IN_BUFFER_SIZE - 1){
        //  // 说明读完了
        //  return 0;
        //}
      }
    }
    return 0;
   //   std::cout << "----recv helper" << std::endl;
  }
  int recver(EventItem* item)
  {
    Epoller* epoller = item->_R;
    int sock = item->_sock;
    int ret = recv_helper(sock, item->_inbuffer); 
    if (ret < 0){
      // error
      return -1;
    }
    else if (ret == 1){
      Peer peer = epoller->_sock_peer[sock];
      std::cout << "[" << peer._ip << "]:[" << peer._port << "]# close" << std::endl; 
      epoller->_sock_peer.erase(sock);
      epoller->DeLEvents(sock);
      close(sock);
      return 0;
    }
    // 对数据包进行分离、反序列化和处理，并响应
    // 1.对数据流进行包与包直接的分离
    std::vector<std::string> v;
    ns_util::Split(item->_inbuffer, v);
      
   //   std::cout << "size:"  << v.size() << std::endl;
    // 2.对每个数据包进行反序列化处理 decode
    for (auto& s : v)
    {
      request rq;
      Peer peer = epoller->_sock_peer[sock];
      //std::cout << s <<  std::endl;
      ns_util::Deserialize(s, rq);
      // 3.构造任务，让线程池进行业务处理
      // 4.形成响应报头
      // 5.写回
      //std::cout << "put"  <<  std::endl;
      Task* t = new Task(peer._port, peer._ip, rq, item);
      tp->Put(t);// 处理 
    }
    return 0;
  }
  int send_helper(int sock, std::string& in)
  {
    size_t total = 0;  
    while (1){
      ssize_t s = send(sock, in.c_str()+total, in.size()-total, 0);
      if (s < 0){
        if (errno == EWOULDBLOCK || errno == EAGAIN){
          // 缓冲区打满了，不能再写入
          // 把已经写入的数据删掉
          in.erase(0, total);
          return 1;
        }
        else if (errno == EINTR){
          continue;
        }
        else{
          std::cerr << "send error, fd: " << sock << std::endl;
          return -1;
        }
      }
      else{
        // normal
        total += s;
        if (total == in.size()){
          in.clear();
          return 0;// 发完了
        }
      }
    }
  }
  int sender(EventItem* item)
  {
    Epoller* epoller = item->_R;
    int sock = item->_sock;
    int ret = send_helper(sock, item->_outbuffer);
    if (ret == 0){
      // 关闭写
      epoller->EnableReadWrite(sock, true, false);
    }
    else if (ret == 1){
      // 继续检测写
      epoller->EnableReadWrite(sock, true, true);
    }
    else{
      return -1;
    }
    return 0;
  }
  int errorer(EventItem* item)
  {
    return 0;
  }
}
